﻿// TabTipWindow.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "TabTipWindow.h"

//#define DefaultTipSharedMemoryName L"DefaultTIPSharedMemory"

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

HFONT g_hfont = NULL;
HINSTANCE g_hInst = NULL;
ATOM g_atom = NULL;
HWND g_hwnd = NULL;
int nWidth = 300, nHeight = 500;

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    LOGFONT logfont;
    GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &logfont);
    logfont.lfItalic = false;//使用斜体
    logfont.lfHeight = 16;//字体高度为16PX
    logfont.lfWeight = 20;//字体宽度为20PX
    logfont.lfCharSet = GB2312_CHARSET;//国标2312
    logfont.lfQuality = CLEARTYPE_QUALITY;
    wsprintf(logfont.lfFaceName, TEXT("%s"), TEXT("微软雅黑"));
    g_hfont = CreateFontIndirect(&logfont);//字体为宋体

    g_hInst = hInstance;
    WNDCLASSEX wcex =
    {
    sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, g_hInst, LoadIcon(NULL, IDI_APPLICATION),
    LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, TEXT("WindowClass"), NULL,
    };
    ATOM atom = RegisterClassEx(&wcex);
    g_atom = atom;
    if (!atom)
        return MessageBox(NULL, TEXT("Cannot register class !"), TEXT("Error"), MB_ICONERROR | MB_OK);
    int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2;
    HWND hWnd = CreateWindowExW(0, (LPCWSTR)atom/*wcex.lpszClassName*/, TEXT("TabTipNotification"), (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU /* | WS_THICKFRAME */ | WS_MINIMIZEBOX),
        nX, nY, nWidth, nHeight, NULL, NULL, g_hInst, NULL);
    if (!hWnd)
        return MessageBox(NULL, TEXT("Cannot create window !"), TEXT("Error"), MB_ICONERROR | MB_OK);
    g_hwnd = hWnd;
    ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);

    HANDLE hShareMemoryFileMap = CreateFileMappingW((HANDLE)-1, NULL, PAGE_READWRITE, 0, sizeof(HWND), L"TabTipNotificationDbgWndShareMemory");
    if (hShareMemoryFileMap)
    {
        LPVOID lpViewFile = MapViewOfFile(hShareMemoryFileMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0);
        if (lpViewFile)
        {
            memcpy(lpViewFile, &g_hwnd, sizeof(HWND));
        }
    }

    ShowWindow(hWnd, SW_SHOWNORMAL);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

#define WM_SHOWINPUTWND (WM_USER + 0x111)
#define WM_HIDEINPUTWND (WM_USER + 0x112)
#define WM_SHOWINPUTTIMER 31
#define WM_HIDEINPUTTIMER 32
HWND g_InputStaticHwnd = NULL;
bool g_bShowingInputWnd = false;
HWND g_InputHwnd = NULL;
#define IDC_HIDEBUTTON 17

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
#define INPUTWINDHEIGHT 300
    static HWND hHideInputWndButton = NULL;
    static int iInputWndHeight = 0;
    switch (message)
    {
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // 分析菜单选择:
        switch (wmId)
        {
        case IDC_HIDEBUTTON:
        {
            ::PostMessage(g_hwnd, WM_HIDEINPUTWND, 0, 0);
        }
        break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
    case WM_SHOWINPUTWND:
    {
        if (g_bShowingInputWnd)
        {
            break;
        }
        g_bShowingInputWnd = true;

        if (g_InputHwnd)
        {
            ShowWindow(g_InputHwnd, SW_HIDE);
            ::DestroyWindow(g_InputHwnd);
            g_InputHwnd = NULL;
        }
        if (hHideInputWndButton)
        {
            ::DestroyWindow(hHideInputWndButton);
            hHideInputWndButton = NULL;
        }

        g_InputHwnd = CreateWindowExW(0, (LPCWSTR)g_atom, TEXT(""), (WS_CHILD /* | WS_VISIBLE */),
            0, nHeight - INPUTWINDHEIGHT, nWidth, INPUTWINDHEIGHT, hWnd, NULL, g_hInst, NULL);

        hHideInputWndButton = CreateWindowExW(0, L"Button", L"↓", WS_CHILD | WS_VISIBLE | BS_PUSHLIKE, 120, 30, 60, 32, g_InputHwnd, (HMENU)IDC_HIDEBUTTON, g_hInst, NULL);

        InvalidateRect(g_InputHwnd, NULL, 1);
        UpdateWindow(g_InputHwnd);

        KillTimer(g_hwnd, WM_HIDEINPUTTIMER);
        SetTimer(g_hwnd, WM_SHOWINPUTTIMER, 4, NULL);
        break;
    }
    case WM_HIDEINPUTWND:
    {
        g_bShowingInputWnd = false;
        KillTimer(g_hwnd, WM_SHOWINPUTTIMER);
        SetTimer(g_hwnd, WM_HIDEINPUTTIMER, 4, NULL);
        break;
    }
    case WM_TIMER:
    {
        if (wParam == WM_SHOWINPUTTIMER)
        {
            iInputWndHeight += 13;
            if (iInputWndHeight > INPUTWINDHEIGHT)
            {
                iInputWndHeight = INPUTWINDHEIGHT;
                KillTimer(g_hwnd, WM_SHOWINPUTTIMER);
            }
            if (g_InputHwnd)
            {
                SetWindowPos(g_InputHwnd, NULL, 0, nHeight - iInputWndHeight, nWidth, iInputWndHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE);
            }
        }
        else if (wParam == WM_HIDEINPUTTIMER)
        {
            if (g_InputStaticHwnd)
            {
                ShowWindow(g_InputStaticHwnd, SW_HIDE);
                ::DestroyWindow(g_InputStaticHwnd);
                g_InputStaticHwnd = NULL;
                InvalidateRect(g_hwnd, NULL, 1);
            }

            iInputWndHeight -= 13;
            if (iInputWndHeight < 0)
            {
                iInputWndHeight = 0;
                KillTimer(g_hwnd, WM_HIDEINPUTTIMER);

                if (g_InputHwnd)
                {
                    ShowWindow(g_InputHwnd, SW_HIDE);
                    ::DestroyWindow(g_InputHwnd);
                    g_InputHwnd = NULL;
                }
            }
            if (g_InputHwnd)
            {
                SetWindowPos(g_InputHwnd, NULL, 0, nHeight - iInputWndHeight, nWidth, iInputWndHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE);
            }
        }
        break;
    }
    case WM_PAINT:
        if (hWnd == g_InputHwnd)
        {
            HDC hdcmem; //内存DC
            HDC hdc;    //设备DC
            HBITMAP hbm;//位图句柄
            PAINTSTRUCT ps;
            hdc = BeginPaint(hWnd, &ps);
            LONG lWidth = ps.rcPaint.right - ps.rcPaint.left;
            LONG lHeight = ps.rcPaint.bottom - ps.rcPaint.top;
            hdcmem = CreateCompatibleDC(hdc); //创建一个兼容设备的内存DC
            hbm = CreateCompatibleBitmap(hdc, lWidth, lHeight);
            HBITMAP old_hbm = (HBITMAP)SelectObject(hdcmem, hbm);

            HBRUSH hbr = (HBRUSH)GetStockObject(COLOR_GRAYTEXT);// CreateSolidBrush(RGB(205, 200, 200));
            HBRUSH old_hbr = (HBRUSH)SelectObject(hdcmem, hbr);
            Rectangle(hdcmem, 0, 0, lWidth, lHeight);
            //FillRect(hdcmem, &ps.rcPaint, HBRUSH(COLOR_GRAYTEXT));
            BitBlt(hdc, 0, 0, lWidth, lHeight, hdcmem, 0, 0, SRCCOPY);
            EndPaint(hWnd, &ps);
            if (old_hbm)
            {
                SelectObject(hdcmem, old_hbm);
            }
            if (old_hbr)
            {
                SelectObject(hdcmem, old_hbr);
            }
            ReleaseDC(hWnd, hdcmem);
            ReleaseDC(hWnd, hdc);
            ::DeleteObject(hdcmem);
            DeleteObject(hbm);
            DeleteObject(hbr);
        }
        else
            return DefWindowProc(hWnd, message, wParam, lParam);
        break;
    case WM_DESTROY:
        if (hWnd == g_hwnd)
        {
            PostQuitMessage(0);
        }
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
